package net.jxtz.jxtzos.authentication.weixin;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.jxtz.jxtzos.authentication.JwtUtils;
import net.jxtz.jxtzos.authentication.MyCsrfTokenRepository;
import net.jxtz.jxtzos.authentication.exception.NotFoundWechatUserInfoException;
import net.jxtz.jxtzos.entity.auth.Wechat;
import net.jxtz.jxtzos.entity.web.R;
import net.jxtz.jxtzos.entity.web.UserInfoDto;
import net.jxtz.jxtzos.mapper.auth.WechatMapper;
import net.jxtz.jxtzos.mapper.redis.RedisMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


/**
 * @author a123
 */
@Slf4j
public class WechatAuthorizationFilter extends UsernamePasswordAuthenticationFilter {

    private final AuthenticationManager authenticationManager;

    private final RedisMapper redisMapper;

    private final WechatMapper wechatMapper;

    private String userName;

    @Value("${cross-path}")
    private String crossPath;

    public WechatAuthorizationFilter(AuthenticationManager authenticationManager, RedisMapper redisMapper, WechatMapper wechatMapper){
        this.authenticationManager = authenticationManager;
        this.redisMapper = redisMapper;
        this.wechatMapper = wechatMapper;
        super.setFilterProcessesUrl("/wechat/login");
        super.setUsernameParameter("userName");
    }

    @SneakyThrows
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        String unionId = request.getParameter("union_id");
        log.info("开始解析微信扫码验证：" + unionId);
        if (StringUtils.isEmpty(unionId)){
            String s = "请输入正确的登陆信息";
            log.error(s);
            unsuccessfulAuthentication(request,response,new NotFoundWechatUserInfoException(s));
            return null;
        }
        this.userName = userName;
        return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("",unionId));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        String s = "登陆成功";
        log.info(s);
        SecurityContextHolder.getContext().setAuthentication(authResult);
        WechatUserDetails userDetails = (WechatUserDetails)authResult.getPrincipal();
        response.setContentType("application/json;charset=utf-8");
        response.setHeader("Access-Control-Allow-Origin", crossPath);
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Allow-Headers","*");
        response.setHeader("Access-Control-Expose-Headers", "*");
        response.setStatus(200);
        log.info(userDetails.toString());
        String token = JwtUtils.TOKEN_PREFIX + JwtUtils.create(userDetails.getUsername(), userDetails);
        response.addHeader("access-token", token);
        redisMapper.set(userDetails.getUsername() + JwtUtils.TOKEN_PARAM_PREFIX, token);
        UserInfoDto userInfoDto = new UserInfoDto();
        Wechat unionId = wechatMapper.selectOne(new QueryWrapper<Wechat>().eq("union_id", userDetails.getUnionId()));
        userInfoDto.setId(userDetails.getId() + "");
        userInfoDto.setNikeName(unionId.getNickname());
        userInfoDto.setUserName(userDetails.getUsername());
        userInfoDto.setHeadUrl(unionId.getHeadimgurl());
        userInfoDto.setAuthorityList(userDetails.getAuthorities());
        PrintWriter writer = response.getWriter();
        writer.write(JSONObject.toJSONString(R.ok().message("登陆成功").data("user", userInfoDto)));
        writer.flush();
        writer.close();
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        String s = "身份校验失败";
        log.error(s);
        failed.printStackTrace();
        redisMapper.deleteKey(userName + JwtUtils.TOKEN_PARAM_PREFIX);
        redisMapper.deleteKey(userName + MyCsrfTokenRepository.CSRF_PARAM);
    }


}
